/*
 * SiFiSy - A File System Simulator
 * Copyright (C) 2010  SevenSoft
 *
 * This file is part of SiFiSy.
 *
 * SiFiSy is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * SiFiSy is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with SiFiSy.  If not, see <http://www.gnu.org/licenses/>.
 */

package sifisy.core;

import java.util.Vector;
import org.jdom.*;
/**
 * Fat32 class describes the type of file system Fat32
 * @author Samuele Faggian
 * @version %I%, %G%
 * @createData 17/02/2010
 */
public class Fat32 extends Simulation{
    private double records;
    private double sizeFileSystem;
    private long maxPartitionSize = 32 * (long)Math.pow(2, 30);

    /**
     * Constructor
     */
    public Fat32() {
        super();
    }

    /**
     * Open an existing FAT32 simulation
     * @param simulationRoot
     */
    @Override
    void open(Element simulationRoot) {
        Element fileSystemRoot = simulationRoot.getChild("fileSystem");
        try {
            records = Double.parseDouble((fileSystemRoot.getChild("records")).
                    getText());
        } catch (NumberFormatException e) {
            System.err.println(
                    "EXCEPTION: Fat32.records \"" + e.getMessage() + "\"");
            records = 0;
        }

        super.open(simulationRoot);
    }

    /**
     * Save the simulation via XML file.
     * @param path
     */
    @Override
    void save(Element simulationRoot) {
        super.save(simulationRoot);
        simulationRoot.addContent("\n    ");
        Element FileSystem = new Element("fileSystem");
        FileSystem.addContent("\n        ");
        FileSystem.addContent(new Element("type").addContent("Fat32"));
        FileSystem.addContent("\n        ");
        FileSystem.addContent(new Element("records").
                addContent(String.valueOf(records)));
        FileSystem.addContent("\n    ");
        simulationRoot.addContent(FileSystem);
        simulationRoot.addContent("\n");
    }

    /**
     * initialize the simulation parameters
     */
    void start(){
        setAddressDimension(32);
        setRecords();
        setSizeFileSystem(calculateFat32Dim());
        super.setMaxLenghtFile(getFileMaxSize());
        super.setInternalFragmentation(fragAverage());
        if(super.getChooseAdvanced())
            super.setAverageReading((int) readingTime());

        super.setInflationIndex(inflactionIndexAverage());
    }

    /**
     * Simply calculates the inflaction index
     * @param sizeFile
     * @return the inflaction index (%)
     */
    double inflactionIndexAverage() {
        long totFileSize = 0;
        for (int index = 0; index < files.size(); index++) {
            totFileSize = totFileSize + files.elementAt(index).getSize();
        }
        return sizeFileSystem / totFileSize * 100;
    }

    /**
     * Returns the dimension of the file system
     * @return double
     */
    double calculateFat32Dim(){
        sizeFileSystem = records * getAddressDimension() / 8;
        return records * getAddressDimension() / 8;
    }

    /**
     * Return the record number
     * @return double
     */
    double getRecordNumber(){
        return records;
    }

    /**
     * Return the maximum size of a file inside the file system
     * @return double
     */
    long getFileMaxSize(){        
        return (long)Math.pow(2, 32);
    }

    /**
     * Method that set maximum file size
     */
    void viewMaxFile(){
        super.setMaxLenghtFile(getFileMaxSize());
    }

    /**
     * Method that set value of records (the number of)
     */
    void setRecords(){
        records = (int) getPartitionDimension() * Math.pow(2, super.
                getPartitionExponent()) / ( getBlockDimension()* Math.pow(2,
                getBlockExponent()) );
    }

    /**
     * Method that return the maximum size of partition
     * @return
     */
    long getMaxPartitionSize() {
        return maxPartitionSize;
    }

       /**
     * Method that set configuration settigs
     * @return vector with configuration settings
     */
    @Override
    public Vector<String[]> getConfigurationValues() {
        Vector<String[]> config = super.getConfigurationValues();

        config.insertElementAt(new String[]{"File System", "FAT32"}, 0);

        return config;
    }

        /**
     * Method that customize the result of Fat32 simulation
     * @return a Vector with String results
     */
    public Vector<String[]> getResultsValues(){
        Vector<String[]> results = new Vector<String[]>();

        results.add(new String[]{Model.translate("maxFile"),
                    String.valueOf(getMaxLenghtFile() / 1024) + " KB"});
        results.add(new String[]{Model.translate("internalFragm"),
                    String.valueOf(getInternalFragmentation())});
        results.add(new String[]{Model.translate("inflactionIndex"),
                    String.valueOf(getInflationIndex()) + " %"});
        results.add(new String[]{Model.translate("fileSystemSize"),
                    String.valueOf(super.getSizeFileSystem() / 1024) + " KB"});
        results.add(new String[]{Model.translate("MFTrecords"),
                    String.valueOf(records / 1024) + " KB"});
       
        if (getChooseAdvanced())
            results.add(new String[]{Model.translate("averageReading"),
                        String.valueOf(getAverageReading()) + " ms"});

        return results;
    }
}
